import ch.sfug.events.ErrorEvent;
import ch.sfug.events.Event;
import ch.sfug.events.HTTPStatusEvent;
import ch.sfug.net.loader.AbstractLoader;

/**
 * @author Marcel
 */

class ch.sfug.net.loader.XMLLoader extends AbstractLoader {

	private var xml:XML;

	/**
	 * constructor
	 * @param xmlUrl the xml url
	 * @param preventCacheing (optional) if true the loaded url will contain a random number to prevent caching. default is false.
	 */
	public function XMLLoader( xmlUrl:String, noCache:Boolean ) {
		super( xmlUrl, noCache );

		xml = new XML();
		xml.ignoreWhite = true;
		var t:XMLLoader = this;

		xml.onLoad = function( suc:Boolean ) {
			t.onLoad( suc );
		};
		
		var o:Object = xml;
		o.onHTTPStatus = function( num:Number ) {
			t.onHTTPStatus( num );
		};

	}

	/**
	 * starts the download of the xml file
	 * @param xmlUrl (optional) reassign url before loading
	 * @param noCache (optional) if true the loaded url will contain a random number to prevent caching. default is false.
	 */
	public function load( xmlUrl:String, noCache:Boolean ):Void {
		url = xmlUrl;
		preventCacheing = noCache;
		xml.parseXML( "" );
		xml.load( url );
		dispatchEvent( new Event( Event.OPEN ) );
	}

	/**
	 * sends a loadvars object to the url and gets the result
	 * @param lv a loadvars object to send to the url and get the result back
	 * @param method (optional) the method how to send the vars. default is POST.
	 * @param xmlUrl (optional) reassign url before loading
	 * @param noCache (optional) if true the loaded url will contain a random number to prevent caching. default is false.
	 */
	public function sendVar( lv:LoadVars, method:String, xmlUrl:String, noCache:Boolean ):Void {
		url = xmlUrl;
		preventCacheing = noCache;
		xml.parseXML( "" );
		method = ( method == undefined ) ? "POST" : method;
		lv.sendAndLoad( url, xml, method );
		dispatchEvent( new Event( Event.OPEN ) );
	}

	/**
	 * sends a loadvars object to the url and gets the result
	 * @param send_xml a xml file to send to the url.
	 * @param xmlUrl (optional) reassign url before loading
	 * @param noCache (optional) if true the loaded url will contain a random number to prevent caching. default is false.
	 */
	public function sendXML( send_xml:XML, xmlUrl:String, noCache:Boolean ):Void {
		this.url = xmlUrl;
		this.preventCacheing = noCache;
		xml.parseXML( "" );
		send_xml.sendAndLoad( url, xml );
		dispatchEvent( new Event( Event.OPEN ) );
	}

	/**
	 * returns the result xml file
	 */
	public function getResult():XML {
		return xml;
	}

	/**
	 * catch the event from the xml to dispatch the complete event
	 */
	private function onLoad( success:Boolean ):Void {
		if( success ) {
			if( xml.status == 0 ) {
				dispatchEvent( new Event( Event.COMPLETE ) );
			} else {
				dispatchEvent( new ErrorEvent( ErrorEvent.ERROR, getErrorDesc( xml.status ) ) );
			}
		} else {
			dispatchEvent( new ErrorEvent( ErrorEvent.ERROR, getErrorDesc( -1 ) ) );
		}
	}

	/**
	 * catch the event from the xml file to dispatch the httpstatus event
	 */
	private function onHTTPStatus( status:Number ):Void {
		dispatchEvent( new HTTPStatusEvent( HTTPStatusEvent.HTTPSTATUS, status ) );
	}

	/**
	 * returns the error description of the xml error
	 */
	private function getErrorDesc(num:Number):String {
		switch (num) {
			case -1:
				return "Could not load XML file: " + _url;
			case -2:
				return "A CDATA section was not properly terminated.";
			case -3:
				return "The XML declaration was not properly terminated.";
			case -4:
				return "The DOCTYPE declaration was not properly terminated.";
			case -5:
				return "A comment was not properly terminated.";
			case -6:
				return "An XML element was malformed.";
			case -7:
				return "Out of memory.";
			case -8:
				return "An attribute value was not properly terminated.";
			case -9:
				return "A start-tag was not matched with an end-tag.";
			case -10:
				return "An end-tag was encountered without a matching start-tag.";
		}
	}
}
